// Transform selected points: x, y, rotation, xscale, yscale // Transform math from Trevor McCauley's various point commands, used with permission // Modified by Aaron Beall 2011 // Version 1.1 var dom = fw.getDocumentDOM(); function TransformPoints(){ //fw.activeTool = 'Subselection'; var IDENTITY_TRANSFORM = "0, 0, 0, 100, 100"; var input; do{ input = prompt("x, y, degrees, xscale, yscale\nnull to reset", fw.TransformPoints_input || IDENTITY_TRANSFORM); if(!input) return; }while(!validateInput()){ if(input.toLowerCase() == "null"){ fw.TransformPoints_input = IDENTITY_TRANSFORM; return null; } if(isNaN(Number(input.split(",").join("")))) return false; } input = input.split(","); var i = input.length; while(i--) input[i] = Number(input[i]); fw.TransformPoints_input = input.join(","); var selNodes = []; for(var i = 0; i < fw.selection.length; i++){ if(fw.selection[i].contours){ for(var c = 0; c < fw.selection[i].contours.length; c++){ var nodes = fw.selection[i].contours[c].nodes; for(var n = 0; n < nodes.length; n++){ if(nodes[n].isSelectedPoint || fw.activeTool != 'Subselection') selNodes.push({r:nodes[n], si:i, ci:c, ni:n, x:nodes[n].x, y:nodes[n].y, predX:nodes[n].predX, predY:nodes[n].predY, succX:nodes[n].succX, succY:nodes[n].succY}); } } } } if(!selNodes.length) return false; var center = nodesCenter(selNodes); scalePoints(input[3], input[4], selNodes, center); rotatePoints(input[2], selNodes, center); movePoints(input[0], input[1], selNodes); for(var i = 0; i < selNodes.length; i++){ var node = selNodes[i]; fw.selection[node.si].contours[node.ci].nodes[node.ni].x = node.x; fw.selection[node.si].contours[node.ci].nodes[node.ni].y = node.y; fw.selection[node.si].contours[node.ci].nodes[node.ni].predX = node.predX; fw.selection[node.si].contours[node.ci].nodes[node.ni].predY = node.predY; fw.selection[node.si].contours[node.ci].nodes[node.ni].succX = node.succX; fw.selection[node.si].contours[node.ci].nodes[node.ni].succY = node.succY; } return true;//moved || rotated || scaled; } try{ TransformPoints(); }catch(e){alert([e.lineNumber, e])} // Move nodes function movePoints(xmove, ymove, nodes){ for(var i = 0; i < nodes.length; i++){ nodes[i].x += xmove; nodes[i].y += ymove; nodes[i].predX += xmove; nodes[i].predY += ymove; nodes[i].succX += xmove; nodes[i].succY += ymove; } return true; } // Rotate nodes by degrees around a center point, default center is the average node coordinate function rotatePoints(angle, nodes, center){ angle *= Math.PI / 180; var ca = Math.cos(angle); var sa = Math.sin(angle); var si, ci, ni; var sn, cn, nn; var n, _x, _y; if(!center) center = nodesCenter(nodes); nn = nodes.length; for (var i = 0; i < nn; i++){ n = nodes[i]; _x = n.x - center.x; _y = n.y - center.y; n.x = center.x + _x * ca - _y * sa; n.y = center.y + _x * sa + _y * ca; _x = n.predX - center.x; _y = n.predY - center.y; n.predX = center.x + _x * ca-_y * sa; n.predY = center.y + _x * sa + _y * ca; _x = n.succX - center.x; _y = n.succY - center.y; n.succX = center.x + _x * ca - _y * sa; n.succY = center.y + _x * sa + _y * ca; } return true; } // Scale nodes around a center point, default center is the average node coordinate function scalePoints(xscale, yscale, nodes, center){ xscale = (xscale || 100) / 100; yscale = (yscale || 100) / 100; var si, ci, ni; var sn, cn, nn; var n, _x, _y; if(!center) center = nodesCenter(nodes); nn = nodes.length; for (var i = 0; i < nn; i++){ n = nodes[i]; _x = n.x - center.x; _y = n.y - center.y; n.x = center.x + _x * xscale; n.y = center.y + _y * yscale; _x = n.predX - center.x; _y = n.predY - center.y; n.predX = center.x + _x * xscale; n.predY = center.y + _y * yscale; _x = n.succX - center.x; _y = n.succY - center.y; n.succX = center.x + _x * xscale; n.succY = center.y + _y * yscale; } return true; } // Find the center coordiange of a set of nodes function nodesCenter(nodes){ var avg = {x:0, y:0}; var nlen = nodes.length; var i = nlen; while(i--){ avg.x += nodes[i].x; avg.y += nodes[i].y; } avg.x /= nlen; avg.y /= nlen; return avg; } // Find the bounds of a set of nodes function nodeBounds(nodes){ var xSorted = [].concat(selNodes).sort(function(a,b){return a.x - b.x}); var ySorted = [].concat(selNodes).sort(function(a,b){return a.y - b.y}); return { left:xSorted[0].x, top:ySorted[0].y, right:xSorted[xSorted.length - 1].x, bottom:ySorted[ySorted.length - 1].y } }